#include <iostream>
#include "tcp_serve.hpp"
#include "socket.hpp"
#include "portecol.hpp"
#include "calculate.hpp"
#include"daemon.hpp"
using namespace protecol_ns;
void Usage(std::string str)
{
    std::cout << "Usage: " << str << " serverport" << std::endl;
}
using callback_t = std::function<response(const request &req)>;
class server
{
public:
    server(callback_t cb)
        : _cb(cb)
    {
    }
    void service_help(socket_sptr sock_ptr, InetAddr client)
    {
        int sockfd = sock_ptr->SockFd();
        LOG(DEBUG, "get new link,info : %s: %d:%d\n", client.Ip(), client.Port(), sockfd);
        std::string clientaddr = "[" + client.Ip() + " : " + std::to_string(client.Port()) + "]#";
        std::string inbuffer;
        while (true) // 死循环一直接收信息，处理信息，发送信息
        {
            request req;
            // 1. 接收报文
            int n = sock_ptr->socked_recv(&inbuffer);
            if (n < 0)
            {
                LOG(DEBUG, "client %s quit\\n", clientaddr.c_str());
                break;
            }
            std::string package;

            // std::cout<<"inbuffer: "<<inbuffer<<std::endl;
            // 2. 分析数据，确认完整报文
            package = dele_header(inbuffer);
            if (package.empty())
                break;
            std::cout << "------------begin-----------------" << std::endl;
            std::cout << "resq string:\n"
                      << package << std::endl;
            // 3. 反序列化
            req.deserializtion(package);
            // 4. 业务处理
            response resp = _cb(req);
            // 5. 对应答做序列化
            std::string send_str;
            resp.serialize(&send_str);

            std::cout << "resp Serialize:" << std::endl;
            std::cout << send_str << std::endl;
            // 6. 添加长度报头
            send_str = add_header(send_str);

            std::cout << "resp Encode:" << std::endl;
            std::cout << send_str << std::endl;
            // 发送数据
            sock_ptr->socked_send(send_str);
        }
    }

private:
    callback_t _cb;
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    uint16_t port = std::stoi(argv[1]);
    calculate cal;
    // Daemon(false,false);
    server calservice(std::bind(&calculate::execute, &cal, std::placeholders::_1));
    io_service_t service = std::bind(&server::service_help, &calservice, std::placeholders::_1, std::placeholders::_2);
    std::unique_ptr<tcp_server> t_ptr = std::make_unique<tcp_server>(port, service);
    t_ptr->loop();
    return 0;
}